# @Time    : 2023/12/21 9:28
# @Author  : 🍁
# @File    : account.py
# @Software: PyCharm
import re

from django.db.models import Q
from django.shortcuts import render, redirect
from django.views import View
from django import http
from django_redis import get_redis_connection

from web.models import User, TransactionRecord, PriceClassify
from web.utils.response_code import RETCODE
from web.utils.scrypty import hash_password, check_password
from web.utils import re_templates
from web.forms import account
from scripts.uid import get_uuid
from datetime import datetime

"""
用户的注册，登录等操作
"""


class RegisterView(View):
    def get(self, request):
        form = account.RegisterForms()
        return render(request, "register.html", {"form": form})

    def post(self, request):
        # form = account.RegisterForms(data=request.POST)
        # # 判断钩子函数是否全部通过
        # if form.is_valid():
        #     print(form.cleaned_data)  # 通过后返回数据
        #     # 保存到数据库中，这个是form自带的一个方法保存到数据库当中
        #     # 可以自动去除数据库当中没有的字段
        #     #
        #     try:
        #         instance = form.save()
        #         print("instance：" + instance)
        #     except Exception as e:
        #         return http.JsonResponse({"code": RETCODE.DBERR, "error": "注册失败"})
        # else:
        #     print("error")
        #     print(form.errors)  # 不通过返回错误信息

        # 两种方法选一种即可
        # 校验前端发送的数据
        username = request.POST.get("username")
        password = request.POST.get("password")
        re_password = request.POST.get("re_password")
        email = request.POST.get("email")
        mobile = request.POST.get("mobile")
        verify_sms = request.POST.get("verify_sms")
        form = account.RegisterForms()  # 注册的表单类

        # 校验数据
        if not all([username, password, email, mobile, verify_sms]):
            return http.HttpResponseForbidden({"code": RETCODE.NECESSARYPARAMERR, "err_msg": "缺少必要参数"})
        if not re.match(re_templates.USERNAME, username):  # 校验用户名格式是否正确
            return http.JsonResponse({"code": RETCODE.USERERR, "errmsg": "用户名不正确"})
        if User.objects.filter(username=username):
            return render(request, "register.html", {"form": form, "sms_err_code": 100, "sms_errmsg": "用户名已存在"})
        if not re.match(re_templates.PASSWORD, password):  # 校验密码格式
            return http.JsonResponse({"code": RETCODE.PWDERR, "errmsg": "密码格式错误"})
        if re_password != password:  # 校验两次密码是否一致
            return http.JsonResponse({"code": RETCODE.CPWDERR, "errmsg": "两次密码不一致"})
        if not re.match(re_templates.EMAIL, email):  # 校验邮箱格式
            return http.JsonResponse({"code": RETCODE.EMAILERR, "errmsg": "邮箱格式错误"})
        if not re.match(re_templates.MOBILE, mobile):  # 校验手机号格式
            return http.JsonResponse({"code": RETCODE.MOBILEERR, "errmsg": "手机号格式错误"})
        # 判断验证码是否过期和是否正确
        redis_conn = get_redis_connection("ver_code")
        code = redis_conn.get("code_%s" % mobile).decode()
        if not code:
            return render(request, "register.html",
                          {"form": form, "sms_err_code": 100, "sms_errmsg": "验证码过期，请重新获取"})
        if code != verify_sms:
            return render(request, "register.html", {"form": form, "sms_err_code": 100, "sms_errmsg": "验证码错误"})

        # 保存数据
        try:
            user = User.objects.create(
                username=username,
                password=hash_password(password),  # 保存加密之后的密码
                email=email,
                mobile=mobile,
            )
            user.save()
            price_classify = PriceClassify.objects.filter(classify=1, title="个人免费版").first()
            # 创建默认交易记录
            user_id = User.objects.get(username=username)
            transaction = TransactionRecord.objects.create(
                state=1,
                order=get_uuid(),
                user=user_id,
                price_classify=price_classify,
                count=0,
                price=0,
                start_date=datetime.now(),
                end_date=None,
            )
            transaction.save()
        except Exception as e:
            print(e)
            return http.JsonResponse({"code": RETCODE.DBERR, "err_msg": "注册失败"})
        # 响应结果
        return render(request, "index.html")


class LoginView(View):
    def get(self, request):
        form = account.LoginForms()
        return render(request, "login.html", {"form": form})

    def post(self, request):
        # 获取前端传过来的信息
        username = request.POST.get("username")
        password = request.POST.get("password")
        image_code = request.POST.get("image_code")
        uuid = request.POST.get("uuid")
        form = account.LoginForms()
        # 验证信息
        if not all(["username", "password"]):
            return http.JsonResponse({"code": RETCODE.NODATAERR, "errmsg": "缺失重要参数"})
        if not re.match(re_templates.USERNAME, username):
            return http.JsonResponse({"code": RETCODE.USERERR, "errmsg": "用户名不正确"})
        if not re.match(re_templates.PASSWORD, password):
            return http.JsonResponse({"code": RETCODE.PWDERR, "errmsg": "密码格式错误"})
        # 从redis 当中获取到图形验证码
        conn = get_redis_connection("ver_code")
        code = conn.get("code_%s" % uuid).decode()
        if not code:
            return render(request, "login.html",
                          {"form": form, "sms_err_code": 100, "sms_errmsg": "验证码超时"})
        image_code = image_code.upper()
        if code != image_code:  # 全部转换成大写判断
            return render(request, "login.html",
                          {"form": form, "sms_err_code": 100, "sms_errmsg": "验证码错误"})
        # 连接数据库
        try:
            conn_object = User.objects.filter(Q(username=username) | Q(email=username)).first()
            if not conn_object:
                return render(request, "login.html",
                              {"form": form, "sms_err_code": 100, "sms_errmsg": "用户名或密码错误"})
            # 在数据库里面拿出来的数据是字符串类型，需要弄成bytes 类型
            conn_password = conn_object.password.strip('b').strip('"').strip("'").encode("utf-8")
            if not check_password(password, conn_password):  # 用户名或密码错误
                return render(request, "login.html",
                              {"form": form, "sms_err_code": 100, "sms_errmsg": "用户名或密码错误"})

            request.session['user_id'] = conn_object.id
            request.session.set_expiry(60 * 60 * 24 * 14)  # 保存用户信息到session中，保存14天

        except Exception:
            return http.HttpResponseForbidden("服务器有误，请重新登录")
        # 登录成功，跳转到主页
        return redirect("index")


class LoginSMSView(View):
    def get(self, request):
        form = account.LoginSMSForm()
        return render(request, "login_sms.html", {"form": form})

    def post(self, request):
        # 获取数据
        mobile = request.POST.get("mobile")
        verify_code = request.POST.get("verify_sms")
        form = account.LoginSMSForm()
        # 校验数据
        if not all(["mobile", "code"]):
            return http.JsonResponse({"code": RETCODE.NODATAERR, "errmsg": "确实重要参数"})
        if not re.match(re_templates.MOBILE, mobile):
            return http.JsonResponse({"code": RETCODE.MOBILEERR, "error": "手机号格式错误"})

        # 从redis当中拿到短信验证码
        redis_conn = get_redis_connection("ver_code")
        code = redis_conn.get("code_%s" % mobile).decode()
        if verify_code != code:
            return render(request, "login_sms.html", {"form": form, "sms_err_code": 100, "sms_errmsg": "验证码错误"})

        try:
            user = User.objects.filter(mobile=mobile).first()
            request.session["user_id"] = user.id
            request.session.set_expiry(60 * 60 * 24 * 14)  # 保存用户信息到session中，保存14天
        except Exception:
            return render(request, "login_sms.html",
                          {"form": form, "sms_err_code": 100, "sms_errmsg": "改手机号未注册"})

        # 登录成功，跳转到主页
        return redirect("index")


class LogoutView(View):
    def get(self, request):
        request.session.flush()  # 清除session当中的数据
        return redirect("index")
